package com.zmj.socket;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 *
 * @author zhangmj
 * @date 2018/9/24 10:41
 *
 * jdk 1.4 以后，java 引入了一个包 new IO Non-Blocking 同步非阻塞的IO
 */
public class NIOServer {

    private int port = 8000;
    private InetSocketAddress address = null;
    private Selector selector;

    public NIOServer(int port) {
        try {
            this.port = port;
            address = new InetSocketAddress(this.port);
            ServerSocketChannel server = ServerSocketChannel.open();
            server.socket().bind(address);
            server.configureBlocking(false);
            selector = Selector.open();
            server.register(selector,SelectionKey.OP_ACCEPT);
            System.out.println("服务器启动完成：" + this.port);



        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void listen(){
        try {
            // 轮询,死循环
            while (true){
                int wait = this.selector.select();
                if(wait ==0){
                    continue;
                }
                // SelectionKey 类似句柄
                Set<SelectionKey> keys = this.selector.selectedKeys();
                // 迭代
                Iterator<SelectionKey> i = keys.iterator();
                while (i.hasNext()){
                    SelectionKey key = i.next();
                    process(key);
                    i.remove();
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void process(SelectionKey key) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        if(key.isAcceptable()){
            ServerSocketChannel sever = (ServerSocketChannel) key.channel();
            SocketChannel client = sever.accept();
            client.configureBlocking(false);// 设置为非阻塞的模式
            client.register(selector, SelectionKey.OP_READ);
        }else if (key.isReadable()){
            SocketChannel client = (SocketChannel) key.channel();
            int len = client.read(buffer);
            if (len > 0){
                buffer.flip();
                String content = new String(buffer.array(), 0 ,len);
                client.register(selector, SelectionKey.OP_WRITE);
                System.out.println(content);
            }
            buffer.clear();
        }else if(key.isWritable()){
            SocketChannel client = (SocketChannel) key.channel();
            client.write(buffer.wrap("Hello World".getBytes()));
            client.close();
        }
    }

    public static void main(String[] args) {
        new  NIOServer(8000).listen();
    }
}
